package com.lckoo.mail.receiver;

import com.sun.mail.iap.ProtocolException;
import com.sun.mail.imap.IMAPFolder;
import com.sun.mail.imap.protocol.IMAPProtocol;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.mail.*;
import javax.mail.event.MessageCountAdapter;
import javax.mail.event.MessageCountEvent;
import javax.mail.internet.MimeMessage;
import java.time.LocalDateTime;
import java.util.Properties;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 邮件监听器
 * 应用启动之后执行监听
 */
@Component
@Slf4j
public class MailListener {

    private ExecutorService mailExecutorService = Executors.newFixedThreadPool(4);
    @Autowired
    private MailReceiverProps mailReceiver;
    @Autowired
    private MailHandler mailHandler;
    /**,
     * imapFolder
     */
    private IMAPFolder folder = null;

    /**
     * 初始化连接
     */
    private void initConnect()  throws Exception{
        Properties props = System.getProperties();
        props.setProperty("mail.imap.auth", "true");
        props.setProperty("mail.store.protocol", mailReceiver.getProtocol());
        props.setProperty("mail.imap.ssl.enable", mailReceiver.getSsl());
        Session session = Session.getInstance(props, null);
        Store store = session.getStore(mailReceiver.getProtocol());
        store.connect(mailReceiver.getHost(), mailReceiver.getPort(), mailReceiver.getUsername(), mailReceiver.getPassword());

        //获取收件箱
        Folder folder = store.getFolder("Inbox");
        if (folder == null || !folder.exists()) {
            log.error("folder not exist");
            throw new RuntimeException("收件邮箱初始化异常");
        }

        //打开收件箱,并设置读写模式,如果不需要修改,则只读模式即可READ_ONLY
        folder.open(Folder.READ_WRITE);
        this.folder = (IMAPFolder) folder;
    }

    /**
     * 定时每10分钟和服务器通信一次，保持连接
     */
    @Scheduled(cron = "${mail.receiver.cron}")
    protected void noop() throws Exception {
        if(!isEnabled()){
            return;
        }
        log.info("定时通信,保持邮箱连接有效,time:{}", LocalDateTime.now());
        if(folder == null){
            log.info("初始化mail 连接");
            initConnect();
        }
        log.info("发送NOOP 命令");
        try {
            Object val = folder.doCommand(new IMAPFolder.ProtocolCommand() {
                public Object doCommand(IMAPProtocol p) throws ProtocolException {
                    p.simpleCommand("NOOP", null);
                    return null;
                }
            });
        } catch (MessagingException e) {
            log.error("NOOP 异常",e);
        }
        log.info("发送NOOP 命令 done!");
    }

    /**
     * 异步监听
     * @throws Exception
     */
    @Async
    public void asyncListener() throws Exception {
        this.listener();
    }

    public void listener() throws Exception {
        if(!isEnabled()){
            return;
        }

        if(folder == null){
            initConnect();
        }

        log.info("开始监听邮箱");

        //监听新邮件
        folder.addMessageCountListener(new MessageCountAdapter() {
            @SneakyThrows
            @Override
            public void messagesAdded(MessageCountEvent e) {
                Message[] messages = e.getMessages();
                log.info("收到新邮件:{}", messages.length);
                for (Message msg : messages) {
                    log.debug("回调业务方法");
                    MailInfo mailInfo = new MailInfo((MimeMessage) msg);
                    //回调业务方法
                    mailExecutorService.submit(()->{
                        mailHandler.doBusiness(mailInfo);
                    });
                    log.debug("回调业务方法success,设置邮件已读");
                    //设置已读
                    msg.setFlag(Flags.Flag.SEEN, true);
                }
            }
        });

        //中断后继续idle
        for (;;) {
            try {
                if(!folder.isOpen()){
                    log.warn("重新打开folder");
                    folder.open(Folder.READ_WRITE);
                }
                folder.idle();
                log.debug("邮件活动。。。");
            }catch (FolderClosedException e){
                log.error("异常:FolderClosedException,",e);
            }

        }
    }

    /**
     * 是否开启
     * @return
     */
    private boolean isEnabled(){
        //支持多节点判断,优先 runMode = true,runNodeKey 为兼容已有系统中已有的配置
        if (!mailReceiver.isRunNode()) {
            String value = System.getenv(mailReceiver.getRunNodeKey()) != null ? System.getenv(mailReceiver.getRunNodeKey()) : "-1";
            if (!mailReceiver.getRunNodeValue().equals(value)) {
                return false;
            }
        }
        return true;
    }
}
